﻿using Microsoft.VisualStudio.TestTools.UnitTesting;
using Oryon.Extensions.Data;
using Oryon.Extensions.Internet;
using Oryon.Extensions.IO;
using Oryon.Extensions.Reflection;
using System;
using System.Collections.Generic;
using System.Data;
using System.IO;
using System.IO.Compression;
using System.Linq;
using System.Xml.Linq;

namespace Oryon.Extensions.CTS.Tests
{
    [TestClass]
    public class UnitTest1
    {
        #region Common Fields

        List<Product> products = new List<Product>()
            {
                new Product{ProductId=1,Name="A"},
                new Product{ProductId=2,Name="B"},
                new Product{ProductId=3,Name="C"},
                new Product{ProductId=4,Name="D"},
                new Product{ProductId=5,Name="E"},
                new Product{ProductId=6,Name="F"},
                new Product{ProductId=1,Name="G"},
                new Product{ProductId=2,Name="H"},
                new Product{ProductId=3,Name="J"},
                new Product{ProductId=4,Name="K"},
                new Product{ProductId=5,Name="L"},
                new Product{ProductId=6,Name="M"}
            };

        #endregion

        [TestMethod]
        public void GetPersonsInBlendedOrderIsOk()
        {
            var result1=products.BlendRandom();
            var result2 = products.BlendRandom();
            Assert.AreNotEqual(result1.First().ProductId, result2.First().ProductId);
            //TODO: Some times both collections are same. Check it.
        }

        [TestMethod]
        public void ZipCurrentFolderIsOk()
        {
            DirectoryInfo dInfo=new DirectoryInfo(Environment.CurrentDirectory);
            bool result=dInfo.CompressFolder(
                string.Format("c:\\{0}.zip",Guid.NewGuid().ToString())
                , CompressionLevel.Optimal
                , true);
            bool expected = true;
            Assert.AreEqual(result, expected);
        }

        [TestMethod]
        public void ConvertProductListToJsonIsOk()
        {
            string result=products.SerializeToJSON();
            string expected = File.ReadAllText(
                Path.Combine(Environment.CurrentDirectory, "ProductListJson.txt")
                );
            Assert.AreEqual(result, expected);
        }

        [TestMethod]
        public void GetNonePrimitiveTypesForDoubleIsOk()
        {
            double salary = 1000.50;
            var result=salary.GetNoneprimitiveProperties();
            Assert.AreNotEqual(result, null);
        }

        [TestMethod]
        public void CompressAnyPDFDocumentFileWithGZipStreamIsOk()
        {
            string sampleFilePath = Path.Combine(Environment.CurrentDirectory, "DomainDrivenDesignQuicklyOnline.pdf");
            byte[] content=File.ReadAllBytes(sampleFilePath);
            byte[] compressedContent=content.Compress(CompressionType.GZip);
            Assert.AreNotEqual(content.Length, compressedContent.Length);
        }

        [TestMethod]
        public void SerializationForDataSetIsOk()
        {
            DataSet newSet = new DataSet("AzonMotorCompany");

            newSet.Tables.Add(CreateProductDataTable());
            newSet.Tables.Add(CreateHumanDataTable());

            string outputFilePath;
            bool result = newSet.BinarySerialize(out outputFilePath);

            Assert.AreEqual(result, true);
            Assert.AreEqual(Path.GetExtension(outputFilePath), ".bin");
        }

        [TestMethod]
        public void CreateHashForParadise1234ForMD5IsOk()
        {
            string sourceValue = "Paradise1234";
            string hashedValue1 = sourceValue.HashedValue(HashType.MD5);
            string hashedValue2 = sourceValue.HashedValue(HashType.MD5);

            Assert.AreEqual(hashedValue1,hashedValue2);
        }

        [TestMethod]
        public void CreateHashForParadise1234ForSHA512IsOk()
        {
            string sourceValue = "Paradise1234";
            string hashedValue1 = sourceValue.HashedValue(HashType.SHA512);
            string hashedValue2 = sourceValue.HashedValue(HashType.SHA512);

            Assert.AreEqual(hashedValue1, hashedValue2);
        }

        [TestMethod]
        public void ConvertBookListToXElementIsOk()
        {
            var books = new List<Book>
            {
                new Book{BookId=1,Title="Pro C# 5.0and the .Net 4.5 Framework", ListPrice=45.55M},
                new Book{BookId=2,Title="Pro WCF", ListPrice=35M}
            };

            XElement result = books.ToXml("Amazon");
            XElement expected = XElement.Parse(@"<Amazon>
  <Book>
    <ListPrice>45.55</ListPrice>
    <Title>Pro C# 5.0and the .Net 4.5 Framework</Title>
    <BookId>1</BookId>
  </Book>
  <Book>
    <ListPrice>35</ListPrice>
    <Title>Pro WCF</Title>
    <BookId>2</BookId>
  </Book>
</Amazon>");
            Assert.AreEqual(result.ToString().Trim(), expected.ToString().Trim());
        }

        [TestMethod]
        public void CompressLoremIpsumToByteArray()
        {
            string loremIpsumContent = @"Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aliquam mattis venenatis ultricies. In consectetur, velit molestie ornare volutpat, orci diam blandit velit, imperdiet pharetra tortor nulla eu neque. Morbi sed velit id purus ornare aliquet eu sed eros. Suspendisse porttitor interdum enim, a aliquet libero bibendum sed. Aenean lobortis lobortis dolor, at malesuada nisi viverra vel. Ut iaculis rhoncus magna sed adipiscing. Vestibulum commodo libero in odio tincidunt quis fermentum urna sodales. Nulla nibh sem, lacinia tristique tincidunt sit amet, porttitor sit amet diam.

Etiam sem sem, luctus et porta eget, rutrum sit amet orci. In congue imperdiet quam eget rhoncus. Morbi pharetra convallis sem ac dapibus. Etiam malesuada nulla nibh. Donec lobortis ligula dui, non pulvinar lacus. Nulla facilisi. Curabitur pretium, lectus vel aliquet placerat, sapien massa pharetra est, vel molestie sem erat eu arcu. Nam euismod, lacus eget porta bibendum, est lectus iaculis turpis, at porttitor ante felis a leo. In nulla leo, dictum nec vestibulum quis, lacinia at arcu.

Aliquam convallis metus pharetra lectus bibendum sagittis. Quisque augue augue, laoreet id elementum commodo, imperdiet ut nunc. Vestibulum eget eros orci. Aenean eros arcu, tempus elementum malesuada non, mollis a elit. In iaculis posuere urna ut venenatis. Nunc nisi ligula, ultricies consectetur sagittis eu, blandit vel eros. Sed non nulla dui, eget blandit lorem. Aenean rutrum vestibulum accumsan. Etiam commodo diam eget nulla fermentum id molestie risus bibendum.";

            byte[] compressedArray=loremIpsumContent.Compress();
            Assert.AreEqual(compressedArray.Length, 702);
        }

        [TestMethod]
        public void CallMethodOnRuntimeIsOk()
        {
            Location loc=new Location();
            object result=loc.Call("Move",new object[]{3,4});
            Assert.AreEqual(result, true);
        }

        [TestMethod]
        public void DumpAnyFileInformationsIsOk()
        {
            var filePath = Path.Combine(Environment.CurrentDirectory, "SomeFile.txt");
            FileInfo fInfo = new FileInfo(filePath);
            string content = fInfo.DumpInfo();
            Assert.AreNotEqual(content, String.Empty);
        }

        [TestMethod]
        public void DirectorySizeGreaterThanZeroIsOk()
        {
            DirectoryInfo c = new DirectoryInfo(@"C:\Program Files\Microsoft.NET\SDK");
            int exceptionCount=0;
            long totlaSize=c.EstimatedTotalSize(ref exceptionCount);
            Assert.AreNotEqual(totlaSize, 0);
        }

        [TestMethod]
        public void WriteSampleEntityCollectionToExcelIsOk()
        {
            Assert.Inconclusive("Not yet completed");
        }

        [TestMethod]
        public void ConvertADataTableToXElementIsOk()
        {
            DataTable dt = new DataTable("ProductTable");
            dt.Columns.Add("ProductId", typeof(Int32));
            dt.Columns.Add("Name", typeof(string));
            dt.Columns.Add("ListPrice", typeof(decimal));

            DataRow row=dt.NewRow();
            row["ProductId"] = 1;
            row["Name"] = "ProductXYZ";
            row["ListPrice"] = 100;

            dt.Rows.Add(row);

            XElement xElement=dt.ConvertToXElement();
            Assert.AreEqual(xElement.Value, @"1ProductXYZ100");
        }

        [TestMethod]
        public void GetGeeksWithBlogsRssContentInHTMLFormatIsOk()
        {
            Uri geeksWithBlogsUri = new Uri("http://feeds.feedburner.com/geekswithblogs");
            string htmlContent=geeksWithBlogsUri.GetRSSFeed();

            Assert.AreNotEqual(htmlContent.Length, 0);
        }

        [TestMethod]
        public void FindAnyControlInForm()
        {
            Assert.Inconclusive("Not yet tested");
        }

        [TestMethod]
        public void CompressFileWithGZipIsOk()
        {
            string file = @"c:\SomeFile.txt";
            FileInfo fInfo = new FileInfo(file);
            bool result=fInfo.Compress();
            Assert.AreEqual(result, true);
        }

        [TestMethod]
        public void SerializeToJSONAnyTTypeInstanceIsOk()
        {
            Product product = new Product { ProductId = 2002, Name = "Test Product Name 2" };
            string result=product.SerializeToJSON();
            Assert.AreEqual(result, @"{""Name"":""Test Product Name 2"",""ProductId"":2002}");
        }

        [TestMethod]
        public void DeserializeJSONStringToRealObjectIsOk()
        {
            string jsonSource = @"{""Name"":""Test Product Name 2"",""ProductId"":2002}";
            Product product=jsonSource.DeserializeFromJSONString<Product>();
            Assert.AreEqual(product.Name,"Test Product Name 2");
            Assert.AreEqual(product.ProductId,2002);
        }

        [TestMethod]
        public void GetPropertyValueAtRuntimeFormObjectInstanceIsOk()
        {
            Product prd = new Product() 
            { 
                ProductId = 1
                , Name = "Test Product Name 1" 
            };

            var value=prd.GetRuntimeValue("Name");
            Assert.AreEqual(value.ToString(), "Test Product Name 1");
        }

        [TestMethod]
        public void CreateDataTableObjectFromContainerAssemblyIsOk()
        {
            string assemblyPath = @"C:\Windows\Microsoft.Net\Framework\v4.0.30319\System.Data.dll";
            object tbl = assemblyPath.CreateObject("DataTable", "Employees");
            Assert.AreNotEqual(tbl, null);                
        }

        [TestMethod]
        public void GetProductDataTableColumnNamesIsOk()
        {
            DataTable tableProduct = CreateProductDataTable();

            var result=tableProduct.GetColumnNames();
            Assert.AreEqual(result[0], "Name");
            Assert.AreEqual(result[1], "ListPrice");
        }

        [TestMethod]
        public void ProductDataTableHasNoRowIsOk()
        {
            var productTable = CreateProductDataTable();
            bool hasRows=productTable.HasRows();
            Assert.AreEqual(hasRows, false);
        }

        [TestMethod]
        public void ProductDataTableHasRowIsOk()
        {
            var productTable = CreateProductDataTable();

            DataRow newRow=productTable.NewRow();
            newRow["Name"] = "Product 1";
            newRow["ListPrice"] = 1000;
            productTable.Rows.Add(newRow);
            bool hasRows = productTable.HasRows();

            Assert.AreEqual(hasRows, true);
        }

        [TestMethod]
        public void ProductDataTableToHTMLIsOk()
        {
            DataTable productTable = CreateProductDataTable();
            FillProductTable(productTable);

            string htmlResponse=productTable.WriteToHTML();
            string expected="<table><tr><th>Name</th><th>ListPrice</th></tr><tr><td>Product 1</td><td>1000</td></tr><tr><td>Product 2</td><td>2000</td></tr><tr><td>Product 3</td><td>3000</td></tr><tr><td>Product 4</td><td>4000</td></tr></table>";
            Assert.AreEqual(htmlResponse,expected);
        }

        [TestMethod]
        public void MyCompanyDataSetToHTMLIsOk()
        {
            DataSet myCompanySet = new DataSet("My Motor Company");

            DataTable productTable = CreateProductDataTable();
            FillProductTable(productTable);

            myCompanySet.Tables.Add(productTable);

            DataTable humanTable= CreateHumanDataTable();
            FillHumanTable(humanTable);

            myCompanySet.Tables.Add(humanTable);

            string htmlResult = myCompanySet.WriteToHTML();
            string expected = "<h1>My Motor Company</h1><br/><div><h2>Product</h2><br/><table><th>Name</th><th>ListPrice</th></tr><tr><td>Product 1</td><td>1000</td></tr><tr><td>Product 2</td><td>2000</td></tr><tr><td>Product 3</td><td>3000</td></tr><tr><td>Product 4</td><td>4000</td></tr></table></div><div><h2>Human</h2><br/><table><th>FirstName</th><th>LastName</th><th>Title</th></tr><tr><td>Bill</td><td>Cosby</td><td>Mr</td></tr><tr><td>Maykil</td><td>Cordin</td><td>Mr</td></tr></table></div><br/>";
            Assert.AreEqual(htmlResult, expected);
        }

        private void FillHumanTable(DataTable humanTable)
        {
            DataRow newRow = humanTable.NewRow();
            newRow["FirstName"] = "Bill";
            newRow["LastName"] = "Cosby";
            newRow["Title"] = "Mr";
            humanTable.Rows.Add(newRow);

            newRow = humanTable.NewRow();
            newRow["FirstName"] = "Maykil";
            newRow["LastName"] = "Cordin";
            newRow["Title"] = "Mr";
            humanTable.Rows.Add(newRow);
        }

        private static void FillProductTable(DataTable productTable)
        {
            DataRow newRow = productTable.NewRow();
            newRow["Name"] = "Product 1";
            newRow["ListPrice"] = 1000;
            productTable.Rows.Add(newRow);

            newRow = productTable.NewRow();
            newRow["Name"] = "Product 2";
            newRow["ListPrice"] = 2000;
            productTable.Rows.Add(newRow);

            newRow = productTable.NewRow();
            newRow["Name"] = "Product 3";
            newRow["ListPrice"] = 3000;
            productTable.Rows.Add(newRow);

            newRow = productTable.NewRow();
            newRow["Name"] = "Product 4";
            newRow["ListPrice"] = 4000;
            productTable.Rows.Add(newRow);
        }

        private static DataTable CreateProductDataTable()
        {
            DataTable tableProduct = new DataTable("Product");

            tableProduct.Columns.Add("Name", typeof(string));
            tableProduct.Columns.Add("ListPrice", typeof(decimal));
            return tableProduct;
        }

        private static DataTable CreateHumanDataTable()
        {
            DataTable tableHuman = new DataTable("Human");

            tableHuman.Columns.Add("FirstName", typeof(string));
            tableHuman.Columns.Add("LastName", typeof(string));
            tableHuman.Columns.Add("Title", typeof(string));
            return tableHuman;
        }
    }
}
